package vehement.game.graphics;

import java.nio.FloatBuffer;

import org.lwjgl.opengl.GL11;

import vehement.game.graphics.primitive.GLBillboard;
import vehement.game.graphics.primitive.GLCube;
import vehement.game.graphics.primitive.GLSquare;
import vehement.game.graphics.primitive.Sprite;
import vehement.game.graphics.primitive.TextureLoader;

public class Ob {

	// usage : GL11.glCallList(Ob.cubeCL);

	public static int		cubeCL;
	public static int		squareCL;

	public static int		wallCL;
	public static int		floorCL;
	//	public static int		gear3;

	public static GLCube cube;
	public static GLSquare square;
	public static GLBillboard billboard;
	public static TextureLoader	textureLoader;
	public static Sprite fireball;
	public Ob(){

		/**
		 * Initial Opengl variables
		 */

		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);

		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_LINEAR);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_LINEAR);

		GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);

		textureLoader = new TextureLoader();
		cube = new GLCube();
		square = new GLSquare();

		fireball = new Sprite(textureLoader, "fireball.png");


		FloatBuffer red = FloatBuffer.wrap(new float[] { 0.8f, 0.1f, 0.0f, 1.0f});
		FloatBuffer green = FloatBuffer.wrap(new float[] { 0.0f, 0.8f, 0.2f, 1.0f});
		FloatBuffer blue = FloatBuffer.wrap(new float[] { 0.2f, 0.2f, 1.0f, 1.0f});

		FloatBuffer white = FloatBuffer.wrap(new float[] { 1.0f, 1.0f, 1.0f, 1.0f});

		//used for generic walls
		wallCL = GL11.glGenLists(1);
		GL11.glNewList(wallCL, GL11.GL_COMPILE);
		GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, white);
		GL11.glTranslatef(0.f, 0.f, .5f);
		cube();
		GL11.glEndList();

		//Used for generic floors
		floorCL = GL11.glGenLists(1);
		GL11.glNewList(floorCL, GL11.GL_COMPILE);
		GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, white);
		square();
		GL11.glEndList();


		cubeCL = GL11.glGenLists(1);
		GL11.glNewList(cubeCL, GL11.GL_COMPILE);
		GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, blue);
		cube();
		GL11.glEndList();

		squareCL = GL11.glGenLists(1);
		GL11.glNewList(squareCL, GL11.GL_COMPILE);
		GL11.glMaterial(GL11.GL_FRONT, GL11.GL_AMBIENT_AND_DIFFUSE, red);
		square();
		GL11.glEndList();


	}


	private void square(){
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		GL11.glBegin(GL11.GL_QUADS);

		GL11.glTexCoord2f(0, 0);
		GL11.glVertex3f(-0.5f, -0.5f, 0);

		GL11.glTexCoord2f(1, 0);
		GL11.glVertex3f(0.5f, -0.5f, 0);

		GL11.glTexCoord2f(1, 1);
		GL11.glVertex3f(0.5f, 0.5f,0);

		GL11.glTexCoord2f(0, 1);
		GL11.glVertex3f(-0.5f, 0.5f,0);

		GL11.glEnd();

		GL11.glDisable(GL11.GL_TEXTURE_2D);
	}

	/*
	private void texSquare(){
		GL11.glBegin(GL11.GL_QUADS);
		  //Quads 1 2 3 4
		GL11.glVertex3f( 0.5f, 0.5f, 0.f);   //V2
		GL11.glVertex3f(-0.5f, 0.5f, 0.f);   //V1
		GL11.glVertex3f(-0.5f,-0.5f, 0.f);   //V4
		GL11.glVertex3f( 0.5f,-0.5f, 0.f);   //V3
		GL11.glEnd();	
	}*/
	void cube(){
		GL11.glEnable(GL11.GL_TEXTURE_2D);

		GL11.glBegin(GL11.GL_QUADS);
		// Front Face
		GL11.glTexCoord2f(0.5f, 0.0f);
		GL11.glVertex3f(-0.5f, -0.5f, 0.5f); // Bottom Left Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 0.0f);
		GL11.glVertex3f(0.5f, -0.5f, 0.5f); // Bottom Right Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 1.0f);
		GL11.glVertex3f(0.5f, 0.5f, 0.5f); // Top Right Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 1.0f);
		GL11.glVertex3f(-0.5f, 0.5f, 0.5f); // Top Left Of The Texture and Qua        
		// Back Face
		GL11.glTexCoord2f(1.0f, 0.0f);
		GL11.glVertex3f(-0.5f, -0.5f, -0.5f); // Bottom Right Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 1.0f);
		GL11.glVertex3f(-0.5f, 0.5f, -0.5f); // Top Right Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 1.0f);
		GL11.glVertex3f(0.5f, 0.5f, -0.5f); // Top Left Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 0.0f);
		GL11.glVertex3f(0.5f, -0.5f, -0.5f); // Bottom Left Of The Texture and Quad
		// Top Face
		GL11.glTexCoord2f(0.0f, 1.0f);
		GL11.glVertex3f(-0.5f, 0.5f, -0.5f); // Top Left Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 0.0f);
		GL11.glVertex3f(-0.5f, 0.5f, 0.5f); // Bottom Left Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 0.0f);
		GL11.glVertex3f(0.5f, 0.5f, 0.5f); // Bottom Right Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 1.0f);
		GL11.glVertex3f(0.5f, 0.5f, -0.5f); // Top Right Of The Texture and Quad
		// Bottom Face
		GL11.glTexCoord2f(1.0f, 1.0f);
		GL11.glVertex3f(-0.5f, -0.5f, -0.5f); // Top Right Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 1.0f);
		GL11.glVertex3f(0.5f, -0.5f, -0.5f); // Top Left Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 0.0f);
		GL11.glVertex3f(0.5f, -0.5f, 0.5f); // Bottom Left Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 0.0f);
		GL11.glVertex3f(-0.5f, -0.5f, 0.5f); // Bottom Right Of The Texture and Quad
		// Right face
		GL11.glTexCoord2f(1.0f, 0.0f);
		GL11.glVertex3f(0.5f, -0.5f, -0.5f); // Bottom Right Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 1.0f);
		GL11.glVertex3f(0.5f, 0.5f, -0.5f); // Top Right Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 1.0f);
		GL11.glVertex3f(0.5f, 0.5f, 0.5f); // Top Left Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 0.0f);
		GL11.glVertex3f(0.5f, -0.5f, 0.5f); // Bottom Left Of The Texture and Quad
		// Left Face
		GL11.glTexCoord2f(0.0f, 0.0f);
		GL11.glVertex3f(-0.5f, -0.5f, -0.5f); // Bottom Left Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 0.0f);
		GL11.glVertex3f(-0.5f, -0.5f, 0.5f); // Bottom Right Of The Texture and Quad
		GL11.glTexCoord2f(1.0f, 1.0f);
		GL11.glVertex3f(-0.5f, 0.5f, 0.5f); // Top Right Of The Texture and Quad
		GL11.glTexCoord2f(0.0f, 1.0f);
		GL11.glVertex3f(-0.5f, 0.5f, -0.5f); // Top Left Of The Texture and Quad
		GL11.glEnd();
		GL11.glDisable(GL11.GL_TEXTURE_2D);
	}

	/**
	 * This draws a unit cube
	 */
	/*
	private void quadCube(){
		GL11.glBegin(GL11.GL_QUAD_STRIP);
		  //Quads 1 2 3 4
		GL11.glVertex3f( 0.5f, 0.5f, 0.5f);   //V2
		GL11.glVertex3f( 0.5f,-0.5f, 0.5f);   //V1
		GL11.glVertex3f( 0.5f, 0.5f,-0.5f);   //V4
		GL11.glVertex3f( 0.5f,-0.5f,-0.5f);   //V3
		GL11.glVertex3f(-0.5f, 0.5f,-0.5f);   //V6
		GL11.glVertex3f(-0.5f,-0.5f,-0.5f);   //V5
		GL11.glVertex3f(-0.5f, 0.5f, 0.5f);   //V8
		GL11.glVertex3f(-0.5f,-0.5f, 0.5f);   //V7
		GL11.glVertex3f( 0.5f, 0.5f, 0.5f);   //V2
		GL11.glVertex3f( 0.5f,-0.5f, 0.5f);   //V1
		GL11.glEnd();
		GL11.glBegin(GL11.GL_QUADS);
		  //Quad 5
		GL11.glVertex3f(-0.5f, 0.5f,-0.5f);   //V6
		GL11.glVertex3f(-0.5f, 0.5f, 0.5f);   //V8
		GL11.glVertex3f( 0.5f, 0.5f, 0.5f);   //V2
		GL11.glVertex3f( 0.5f, 0.5f,-0.5f);   //V4
		  //Quad 6
		GL11.glVertex3f(-0.5f,-0.5f, 0.5f);   //V7
		GL11.glVertex3f(-0.5f,-0.5f,-0.5f);   //V5
		GL11.glVertex3f( 0.5f,-0.5f,-0.5f);   //V3
		GL11.glVertex3f( 0.5f,-0.5f, 0.5f);   //V1
		GL11.glEnd();	
	}
	 */

	/**
	 * Draw a gear wheel.  You'll probably want to call this function when
	 * building a display list since we do a lot of trig here.
	 *
	 * @param inner_radius radius of hole at center
	 * @param outer_radius radius at center of teeth
	 * @param width width of gear
	 * @param teeth number of teeth
	 * @param tooth_depth depth of tooth
	 */
	private void gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
		int i;
		float r0, r1, r2;
		float angle, da;
		float u, v, len;

		r0 = inner_radius;
		r1 = outer_radius - tooth_depth / 2.0f;
		r2 = outer_radius + tooth_depth / 2.0f;

		da = 2.0f * (float) Math.PI / teeth / 4.0f;

		GL11.glShadeModel(GL11.GL_FLAT);

		GL11.glNormal3f(0.0f, 0.0f, 1.0f);

		// draw front face 
		GL11.glBegin(GL11.GL_QUAD_STRIP);
		for (i = 0; i <= teeth; i++) {
			angle = i * 2.0f * (float) Math.PI / teeth;
			GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
			if (i < teeth) {
				GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
				GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da),
						width * 0.5f);
			}
		}
		GL11.glEnd();

		// draw front sides of teeth 
		GL11.glBegin(GL11.GL_QUADS);
		for (i = 0; i < teeth; i++) {
			angle = i * 2.0f * (float) Math.PI / teeth;
			GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + 2.0f * da), r2 * (float) Math.sin(angle + 2.0f * da), width * 0.5f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle + 3.0f * da), r1 * (float) Math.sin(angle + 3.0f * da), width * 0.5f);
		}
		GL11.glEnd();

		// draw back face 
		GL11.glBegin(GL11.GL_QUAD_STRIP);
		for (i = 0; i <= teeth; i++) {
			angle = i * 2.0f * (float) Math.PI / teeth;
			GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
			GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
			GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
		}
		GL11.glEnd();

		// draw back sides of teeth 
		GL11.glBegin(GL11.GL_QUADS);
		for (i = 0; i < teeth; i++) {
			angle = i * 2.0f * (float) Math.PI / teeth;
			GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
		}
		GL11.glEnd();

		// draw outward faces of teeth 
		GL11.glBegin(GL11.GL_QUAD_STRIP);
		for (i = 0; i < teeth; i++) {
			angle = i * 2.0f * (float) Math.PI / teeth;
			GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), width * 0.5f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle), r1 * (float) Math.sin(angle), -width * 0.5f);
			u = r2 * (float) Math.cos(angle + da) - r1 * (float) Math.cos(angle);
			v = r2 * (float) Math.sin(angle + da) - r1 * (float) Math.sin(angle);
			len = (float) Math.sqrt(u * u + v * v);
			u /= len;
			v /= len;
			GL11.glNormal3f(v, -u, 0.0f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), width * 0.5f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + da), r2 * (float) Math.sin(angle + da), -width * 0.5f);
			GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), width * 0.5f);
			GL11.glVertex3f(r2 * (float) Math.cos(angle + 2 * da), r2 * (float) Math.sin(angle + 2 * da), -width * 0.5f);
			u = r1 * (float) Math.cos(angle + 3 * da) - r2 * (float) Math.cos(angle + 2 * da);
			v = r1 * (float) Math.sin(angle + 3 * da) - r2 * (float) Math.sin(angle + 2 * da);
			GL11.glNormal3f(v, -u, 0.0f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), width * 0.5f);
			GL11.glVertex3f(r1 * (float) Math.cos(angle + 3 * da), r1 * (float) Math.sin(angle + 3 * da), -width * 0.5f);
			GL11.glNormal3f((float) Math.cos(angle), (float) Math.sin(angle), 0.0f);
		}
		GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), width * 0.5f);
		GL11.glVertex3f(r1 * (float) Math.cos(0), r1 * (float) Math.sin(0), -width * 0.5f);
		GL11.glEnd();

		GL11.glShadeModel(GL11.GL_SMOOTH);

		// draw inside radius cylinder 
		GL11.glBegin(GL11.GL_QUAD_STRIP);
		for (i = 0; i <= teeth; i++) {
			angle = i * 2.0f * (float) Math.PI / teeth;
			GL11.glNormal3f(-(float) Math.cos(angle), -(float) Math.sin(angle), 0.0f);
			GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), -width * 0.5f);
			GL11.glVertex3f(r0 * (float) Math.cos(angle), r0 * (float) Math.sin(angle), width * 0.5f);
		}
		GL11.glEnd();
	}
}
